<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Common {

	var $_parent_name = '';

	function __construct()
	{
		// If the magic __get() or __set() methods are used in a Model references can't be used.
		$this->_assign_libraries( (method_exists($this, '__get') OR method_exists($this, '__set')) ? FALSE : TRUE );
		
		// We don't want to assign the model object to itself when using the
		// assign_libraries function below so we'll grab the name of the model parent
		$this->_parent_name = ucfirst(get_class($this));		
	
		log_message('debug', "Common Class Initialized");
	}
	
	function _assign_libraries($use_reference = TRUE)
	{
		$CI =& get_instance();				
		foreach (array_keys(get_object_vars($CI)) as $key)
		{
			if ( ! isset($this->$key) AND $key != $this->_parent_name)
			{			
				// In some cases using references can cause
				// problems so we'll conditionally use them
				if ($use_reference == TRUE)
				{
					$this->$key = NULL; // Needed to prevent reference errors with some configurations
					$this->$key =& $CI->$key;
				}
				else
				{
					$this->$key = $CI->$key;
				}
			}
		}		
	}



	function id_exists($table_name = '', $id = null)
	{
		return ($this->get_id_from_criteria($table_name, array('id' => $id)) !== false);
	}
	
	function key_exists($table_name = '', $key = null)
	{
		return ($this->get_key_from_criteria($table_name, array('nkey' => $key)) !== false);
	}
	
	function get_id_from_key($table_name = '', $key = null)
	{
		return $this->get_id_from_criteria($table_name, array('nkey' => $key));
	}
	
	function get_description_from_key($table_name = '', $key = null)
	{
		return $this->get_field_from_key($table_name, 'description', $key);
	}
	
	function get_key_from_id($table_name= '', $id = null)
	{
		return $this->get_key_from_criteria($table_name, array('id' => $id));
	}
	
	function get_description_from_id($table_name = '', $id = null)
	{
		return $this->get_field_from_id($table_name, 'description', $id);
	}
	
	function get_id_from_criteria($table_name = '', $criteria = array())
	{
		return $this->get_field_from_criteria($table_name, 'id', $criteria);
	}
	
	function get_key_from_criteria($table_name = '', $criteria = array())
	{
		return $this->get_field_from_criteria($table_name, 'nkey', $criteria);
	}
	
	function get_description_from_criteria($table_name = '', $criteria = array())
	{
		return $this->get_field_from_criteria($table_name, 'description', $criteria);
	}
	
	function get_field_from_criteria($table_name = '', $field = '', $criteria = array())
	{
		$this->db->select($field)->from($table_name)->where($criteria);
		$query = $this->db->get();
		$result = $query->result_array();
		reset($result);
		$result = current($result);
		if (isset($result[$field])) {
			$result = $result[$field];
		} else {
			$result = false;
		}
		return $result;
	}
	
	function get_field_from_id($table_name = '', $field = '', $id = '')
	{
		return $this->get_field_from_criteria($table_name, $field, array('id' => $id));
	}
	
	function get_field_from_key($table_name = '', $field = '', $key = '')
	{
		return $this->get_field_from_criteria($table_name, $field, array('nkey' => $key));
	}

	function get_application_id($prefix = null)
	{
		return $this->get_field_from_key('sys_m_application', 'id', $prefix);
	}
	
	function get_area_id($prefix = null)
	{
		return $this->get_field_from_key('sys_r_area', 'id', $prefix);
	}	
	
	function get_application_prefix($id = null)
	{
		return $this->get_field_from_id('sys_m_application', 'nkey', $id);
	}
	
	function get_area_prefix($id = null)
	{
		return $this->get_field_from_id('sys_r_area', 'nkey', $id);
	}
	
	function get_application_description($val = null)
	{
		if (is_numeric($val)) {
			return $this->get_application_description_from_id($val);
		} else {
			return $this->get_application_description_from_prefix($val);
		}
	}
	
	function get_area_description($val = null)
	{
		if (is_numeric($val)) {
			return $this->get_area_description_from_id($val);
		} else {
			return $this->get_area_description_from_prefix($val);
		}
	}

	function get_unit_description($val = null)
	{
		if (is_numeric($val)) {
			return $this->get_unit_description_from_id($val);
		} else {
			return $this->get_unit_description_from_key($val);
		}
	}
	
	function get_application_description_from_id($id = null)
	{
		return $this->get_field_from_id('sys_m_application', 'description', $id);
	}
	
	function get_area_description_from_id($id = null)
	{
		return $this->get_field_from_id('sys_r_area', 'description', $id);
	}
	
	function get_unit_description_from_id($id = null)
	{
		return $this->get_field_from_id('sys_d_unit', 'description', $id);
	}
	
	function get_application_description_from_prefix($prefix = null)
	{
		return $this->get_application_description_from_key($prefix);
	}
	
	function get_area_description_from_prefix($prefix = null)
	{
		return $this->get_area_description_from_key($prefix);
	}
	
	function get_application_description_from_key($key = null)
	{
		return $this->get_field_from_key('sys_m_application', 'description', $key);
	}
	
	function get_area_description_from_key($key = null)
	{
		return $this->get_field_from_key('sys_r_area', 'description', $key);
	}	
	
	function get_unit_description_from_key($key = null)
	{
		return $this->get_field_from_key('sys_d_unit', 'description', $key);
	}
	
	function get_unit_name($unit) {
		if (@substr($unit, 3, 1) == '/') { // controller of an application
			$unit = substr($unit, 4);
		}
		
		return humanize($unit);
	}	
	
	function current_user()
	{
		return $this->current_user_key();
	}
	
	function anchor_current_user()
	{
		return anchor('user/view_profile', $this->current_user());
	}

	function current_user_id()
	{
		$user_id = $this->session->userdata('user_id');
		if (!$user_id)
			$user_id = 0;
		return $user_id;
	}

	function current_user_key()
	{
		return $this->session->userdata('user');
	}
	
	function current_role()
	{
		return $this->current_role_desc();
	}
	
	function current_role_id()
	{
		return $this->get_id_from_key('sys_m_role', $this->current_role_key());
	}
	
	function current_role_key()
	{
		$role_key = $this->session->userdata('role');
		if (!$role_key) {
			$role_key = $this->get_key_from_id('sys_m_role', 0); // guest
		}
		return $role_key;
	}
	
	function current_role_desc()
	{
		$role_desc = $this->session->userdata('role_desc');
		if (!$role_desc) {
			$role_desc = $this->get_field_from_key('sys_m_role', 'description', $this->current_role_key());
		}
		return $role_desc;
	}
	
	function anchor_current_role_desc()
	{
		return anchor('user/change_role', $this->current_role_desc());
	}
	
	function flash_message($message = null, $level = 0 )
	{
		if (!is_null($message)) {
			$this->session->set_flashdata('message', $message);
			$this->session->set_flashdata('message_level', $level);
		}
	}
	
	function get_table_caption($table_name) {
		$result = $this->get_field_from_criteria('sys_m_table', 'caption', array('nkey' => $table_name));
		if (!$result) {
			return 'TABLE: '.$table_name;
		} else {
			return $result;
		}
	}
	
	function find_controller_from_table($table_name) {
		$map = directory_map('system/application/controllers');

		foreach($map as $filename) {
			$content = file_get_contents('system/application/controllers/'.$filename);
			if (stripos($content, $table_name))
				return basename($filename, ".php");
		}
		return false;
	}
	
	function get_foreign_key_pair($db, $table_name, $detail_table_name) {
		$query  = 'select COLUMN_NAME, REFERENCED_COLUMN_NAME from ';
		$query .= 'information_schema.KEY_COLUMN_USAGE where ';
		$query .= 'TABLE_NAME<>REFERENCED_TABLE_NAME and ';
		$query .= 'TABLE_SCHEMA = ? and TABLE_NAME = ? and REFERENCED_TABLE_SCHEMA = ? and REFERENCED_TABLE_NAME = ?';
		$foreigners = $this->db->query($query, array($db, $detail_table_name, $db, $table_name))->result_array();
		reset($foreigners);
		return current($foreigners);
	}
	
	function get_referencer_tables($db, $table_name) {
		$query  = 'select TABLE_NAME from ';
		$query .= 'information_schema.KEY_COLUMN_USAGE where ';
		$query .= 'TABLE_NAME<>REFERENCED_TABLE_NAME and ';
		$query .= 'TABLE_SCHEMA = ? and REFERENCED_TABLE_NAME = ?';
		$foreigners = $this->db->query($query, array($db, $table_name))->result_array();
		return $foreigners;
	}
	
	function get_foreign_key_pairs($db, $table_name) {	
		$query  = 'select COLUMN_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME from ';
		$query .= 'information_schema.KEY_COLUMN_USAGE where ';
		$query .= 'TABLE_NAME<>REFERENCED_TABLE_NAME and ';
		$query .= 'TABLE_SCHEMA = ? and TABLE_NAME = ?';
		$foreigners = $this->db->query($query, array($db, $table_name))->result_array();
		return $foreigners;
	}
	
	function who_am_i(&$data, $fields = array(), $type = NULL) { //jika $fields=true, selalu isi (u*, d*, i*)
		
		if (!is_null($type) && (in_array($type = strtolower($type), array('crea', 'upd')))) {
			if (($fields === TRUE) || in_array('u'.$type, $fields))
				$data['u'.$type]	= $this->current_user_key();
			if (($fields === TRUE) || in_array('d'.$type, $fields))
				$data['d'.$type] = unix_to_mysql(now());
			if (($fields === TRUE) || in_array('i'.$type, $fields))
				$data['i'.$type] = $this->input->ip_address();
		}
				
		return $data;
	}
	
	function number_to_words($number, $lang='en') {
		switch($lang) {
			case 'id':
				// WARNING: due to php's numerical limitation, this function is only accurate up to kuadriliun
				if (!function_exists('_number_to_words_convert_id')) {
					function _number_to_words_convert_id($n) {
						$dasar = array('nol', 'satu', 'dua', 'tiga', 'empat', 'lima', 'enam', 'tujuh', 'delapan', 'sembilan');
						$angka = array(1000000000000000000000000000000000, 1000000000000000000000000000000, 1000000000000000000000000000, 1000000000000000000000000, 1000000000000000000000, 1000000000000000000, 1000000000000000, 1000000000000, 1000000000, 1000000, 1000, 100, 10, 1);
						$satuan = array('desiliun', 'noniliun', 'oktiliun', 'septiliun', 'sekstiliun', 'kuintiliun', 'kuadriliun', 'triliun', 'miliar', 'juta', 'ribu', 'ratus', 'puluh', '');
						
						if ($n>0) {
							$i=0;
							while($n!=0){
								$count = (int)($n/$angka[$i]);
								if($count>=10) {
									$str .= _number_to_words_convert_id($count). " ".$satuan[$i]." ";
								} else if($count > 0 && $count < 10) {
									$str .= $dasar[$count] . " ".$satuan[$i]." ";
								}
								$n -= $angka[$i] * $count;
								$i++;
							}
							
							$str = preg_replace("/satu puluh (\w+)/i","\\1 belas",$str);
							$str = preg_replace("/satu (ribu|ratus|puluh|belas)/i","se\\1",$str);
						} else if ($n==0) {
							$str = $dasar[$n];
						} else {
							$str = 'minus '._number_to_words_convert_id(-$n);
						}
						return $str;
					}
				}
				return _number_to_words_convert_id($number);
				break;
		}
	}
	
	function check_permission($application = false, $unit = false, $function = false) {
			/*echo "check permission ";
			var_dump($application);
			var_dump($unit);
			var_dump($function);*/
			
		// mengambil id user yang sedang login dan rolenya dari session				
			$user = $this->current_user_key();
			$role = $this->current_role_key();
		
		// cek permission untuk mengakses aplikasi		
			$allowed = false;				
					
			/*
			APL CON FUN
			0   0   0
			0   1   0
			0   0   1
			0   1   1
			1   0   0
			1   1   0
			1   0   1
			1   1   1
			*/
			
			// check all user all application
			//echo $role;

			$this->db->select('allowed')->from('sys_x_app_privilege')->where('`key_sys_role` IS NULL AND `key_sys_application` IS NULL AND (NOW() >= `dstart` OR `dstart` IS NULL) AND (NOW() <= `dend` OR `dend` IS NULL)');
			$_allowed = $this->db->get()->result_array();
			
			if (count($_allowed)>0) {
				$allowed = (($_allowed[0]['allowed']) == 1);
			}
			//var_dump($allowed);
			
			// check all user specific application		
			if ($application) {
				$this->db->select('allowed')->from('sys_x_app_privilege')->where('`key_sys_role` IS NULL AND `key_sys_application` = '.$this->db->escape($application).' AND (NOW() >= `dstart` OR `dstart` IS NULL) AND (NOW() <= `dend` OR `dend` IS NULL)');
				$_allowed = $this->db->get()->result_array();			
				if (count($_allowed)>0) {
					$allowed = (($_allowed[0]['allowed']) == 1);
				}	
				//var_dump($allowed);
			}
			
			// check specific user all application
			if ($role) {
				$this->db->select('allowed')->from('sys_x_app_privilege')->where('`key_sys_role` = '.$this->db->escape($role).' AND `key_sys_application` IS NULL AND (NOW() >= `dstart` OR `dstart` IS NULL) AND (NOW() <= `dend` OR `dend` IS NULL)');
				$_allowed = $this->db->get()->result_array();				
				if (count($_allowed)>0) {
					$allowed = (($_allowed[0]['allowed']) == 1);
				}
				//var_dump($allowed);
			}
			
			// check specific user specific unit of all application
			
			// check specific user specific function of all unit of all application
			
			// check specific user specific function of specific unit of all application
			
			// check specific user specific application
			if (($role) && ($application)) {
				$this->db->select('allowed')->from('sys_x_app_privilege')->where('`key_sys_role` = '.$this->db->escape($role).' AND `key_sys_application` = '.$this->db->escape($application).' AND (NOW() >= `dstart` OR `dstart` IS NULL) AND (NOW() <= `dend` OR `dend` IS NULL)');
				$_allowed = $this->db->get()->result_array();
				if (count($_allowed)>0) {
					$allowed = (($_allowed[0]['allowed']) == 1);
				}
				//var_dump($allowed);
			}
			
			// check specific user specific unit of specific application
			if (($role) && ($unit)) {
				$this->db->select('allowed')->from('sys_x_unit_privilege')->where('`key_sys_role` = '.$this->db->escape($role).' AND `key_sys_unit` = '.$this->db->escape($unit).' AND (NOW() >= `dstart` OR `dstart` IS NULL) AND (NOW() <= `dend` OR `dend` IS NULL)');
				$_allowed = $this->db->get()->result_array();
				if (count($_allowed)>0) {
					$allowed = (($_allowed[0]['allowed']) == 1);
				}
				//var_dump($allowed);
			}
			
			// check specific user specific function of all unit of specific application
			
			// check specific user specific function of specific unit of specific application
			if (($role) && ($function)) {
				$this->db->select('allowed')->from('sys_x_func_privilege')->where('`key_sys_role` = '.$this->db->escape($role).' AND `key_sys_function` = '.$this->db->escape($function).' AND (NOW() >= `dstart` OR `dstart` IS NULL) AND (NOW() <= `dend` OR `dend` IS NULL)');
				$_allowed = $this->db->get()->result_array();
				//var_dump($_allowed);
				if (count($_allowed)>0) {
					$allowed = (($_allowed[0]['allowed']) == 1);
				}
				//var_dump($allowed);
			}
			
		return $allowed;
	}
	
	function anchor($uri = '', $title = '', $attributes = '', $str_disabled = false)
	{
		$application = get_application_from_uri($uri);
		$unit = get_unit_from_uri($uri);
		$function = get_function_from_uri($uri);

		if ($this->check_permission($application, $unit, $function)) {
			return anchor($uri, $title, $attributes);
		} else {
			if ($str_disabled) {
				return $str_disabled;
			} else {
				return $title;
			}
		}
	}
	
	function get_options_from_uri($uri = NULL) {	
		if (is_null($uri)) {
			$uri = $this->uri->uri_string();
		}
	
		$data = array();
		$multikeys = false;
				
		$fs = find_function_segment_from_uri($uri);

		if (is_string($uri)) {
			$uri = uri_segment_array($uri);
		}		
				
		$nd = count($uri);
		$ns = $nd - $fs;
		
		if (count($uri)>$fs) {
			for($i = 0; $i<$ns/2; $i++) {
				$key = $uri[$fs+1 + 2*$i];
				$value = $uri[$fs+1 + 2*$i+1];
						
				if (in_arrayi($key, array('record', 'criteria', 'sort_asc_by', 'sort_desc_by', 'from', 'count', 'page', 'table', 'field', 'ref_field', 'query', 'filter', 'type'))) {				
					$multikeys = false;
					$filter = false;
				
					if (in_arrayi($key, array('criteria', 'sort_asc_by', 'sort_desc_by', 'table', 'field', 'ref_field', 'query'))) {
						$value = decode_from_uri($value);
					}
					
					if ((strcasecmp($key, 'record')==0) && (is_empty($data['keys']))) {
						if (is_numeric($value)) {
							$data['keys']['id'] = $value;
						} else if (strcasecmp($value, 'with_keys')==0) {
							$multikeys = true;
						} else {
							$data['keys']['nkey'] = decode_from_uri($value);
						}
					} else if (in_arrayi($key, array('sort_asc_by', 'sort_desc_by'))) {
						$data['order_by']['field'] = $value;
						if (strcasecmp($key, 'sort_asc_by')==0) {
							$data['order_by']['type'] = 'ASC';
						} else {
							$data['order_by']['type'] = 'DESC';
						}
					} else if (strcasecmp($key, 'filter')==0) {
						$filter = true;
					} else {
						$data[$key] = $value;					
					}			
				} else {
					if ($multikeys) {
						$data['keys'][decode_from_uri($key)] = decode_from_uri($value);
					} else if ($filter) {
						$data['filter'][decode_from_uri($key)] = decode_from_uri($value);
					}
				}
			}
		}
		
		return $data;
	}
	
	function create_uri_from_options($options = NULL) {
		$result = '';
		if (is_array($options)) {
			if (isset($options['keys'])) $result .= $this->create_uri_record_part($options['keys']).'/';
			if (isset($options['criteria'])) $result .= $this->create_uri_criteria_part($options['criteria']).'/';
			if (isset($options['order_by'])) $result .= $this->create_uri_sort_by_part($options['order_by']['field'], $options['order_by']['type']).'/';
			if (isset($options['filter'])) $result .= $this->create_uri_filter_part($options['filter']).'/';
			if (isset($options['from'])) $result .= $this->create_uri_from_part($options['from']).'/';
			if (isset($options['count'])) $result .= $this->create_uri_count_part($options['count']).'/';
			if (isset($options['page'])) $result .= $this->create_uri_page_part($options['page']).'/';
			if (isset($options['table'])) $result .= $this->create_uri_table_part($options['table']).'/';			
			if (isset($options['field'])) $result .= $this->create_uri_field_part($options['field']).'/';
			if (isset($options['ref_field'])) $result .= $this->create_uri_ref_field_part($options['ref_field']).'/';
			if (isset($options['query'])) $result .= $this->create_uri_query_part($options['query']).'/';			
		}
		return $result;
	}
		
	function create_uri_record_part($properties) {

		//print_r_pre($properties);

		if (is_null_or_false($properties)) {
			$result = '';
		} else {
			$result = 'record/';
			if (!is_array($properties)) {
				if (is_numeric($properties)) {
					$result .= $properties;
				} else {
					$result .= encode_for_uri($properties);
				}
			} else {
				if (isset($properties['id'])) {
					$result .= $properties['id'];
				} else if (isset($properties['nkey'])) {
					$result .= encode_for_uri($properties['nkey']);
				} else {
					$result .= 'with_keys';
					foreach($properties as $idx => $value) {
						$result .= '/'.encode_for_uri($idx).'/'.encode_for_uri($value);
					}
				}
			}
		}
		return $result;
	}
	
	function create_uri_criteria_part($criteria) {
		if (is_null_or_false($criteria)) {
			$result = '';
		} else {
			$result = 'criteria/'.encode_for_uri($criteria);
		}
		return $result;
	}
	
	function create_uri_from_part($from) {
		if (is_null_or_false($from)) {
			$result = '';
		} else {
			$result = 'from/'.$from;
		}
		return $result;
	}
	
	function create_uri_count_part($count) {
		if (is_null_or_false($count)) {
			$result = '';
		} else {
			$result = 'count/'.$count;
		}
		return $result;
	}
	
	function create_uri_page_part($page) {
		if (is_null_or_false($page)) {
			$result = '';
		} else {
			$result = 'page/'.$page;
		}
		return $result;
	}

	function create_uri_table_part($table) {
		if (is_null_or_false($table)) {
			$result = '';
		} else {
			$result = 'table/'.encode_for_uri($table);
		}
		return $result;
	}
	
	function create_uri_field_part($field) {
		if (is_null_or_false($field)) {
			$result = '';
		} else {
			$result = 'field/'.encode_for_uri($field);
		}
		return $result;
	}
	
	function create_uri_ref_field_part($field) {
		if (is_null_or_false($field)) {
			$result = '';
		} else {
			$result = 'ref_field/'.encode_for_uri($field);
		}
		return $result;
	}
	
	function create_uri_query_part($query) {
		if (is_null_or_false($query)) {
			$result = '';
		} else {
			$result = 'query/'.encode_for_uri($query);
		}
		return $result;
	}
		
	function create_uri_sort_by_part($field, $type) {
		if (is_null_or_false($field) || is_null_or_false($type)) {
			$result = '';
		} else {
			if (strcasecmp($type, 'ASC')==0) {
				$result = 'sort_asc_by/';
			} else if (strcasecmp($type, 'DESC')==0) {
				$result = 'sort_desc_by/';
			}
			$result .= encode_for_uri($field);
		}
		return $result;
	}
	
	function create_uri_filter_part($filter) {
		if (is_null_or_false($filter)) {
			$result = '';
		} else {
			$result = 'filter/by';

			foreach($filter as $idx => $value) {
				$result .= '/'.encode_for_uri($idx).'/'.encode_for_uri($value);
			}
		}
		return $result;
	}	
	
	function mask_password(&$password, $update = true) {
		$masked = repeater('*', strlen($password));
		if ($update) {
			$password = $masked;
		}
		return $masked;
	}
	
	function create_download_button($filename, &$data, $update = true) {
		$encoded_data = encode_for_uri($data);
		
		if (is_null_or_false($filename) || is_empty($filename)) {
			$filename = uniqid('file_').'.bin';
		}
		
		if (!is_empty($encoded_data)) {
			$d = form_open('file/download');			
			$d.= form_hidden('filename', $filename);
			$d.= form_hidden('data', $encoded_data);
			$d.= form_submit('__submit', $filename);
			$d.= form_close();
		} else {
			$d = '';
		}
		
		if ($update) {
			$data = $d;
		}
		return $d;
	}
	
	function create_fk_lov($field, $set_value, $fk_table, $fk_value, $controller, $attr = '', $shown_field = null) {
		$fk_field = $fk_value;
		if (!is_null($shown_field)) {
			if (!is_array($fk_field)) {
				$fk_field = array($fk_field);
			}

			$fk_field = array_merge($fk_field, array($shown_field));
		} else {
			$shown_field = $fk_value[$field];
		}
		$this->db->select($fk_field)->from($fk_table);
		$query = $this->db->get();
		$result = $query->result_array();
		//print_r_pre($result);
		
		$options = array();
		foreach ($result as $ridx => $rval) {
			if (!is_null($rval[$fk_value[$field]])) {
				$options[$rval[$fk_value[$field]]] = $rval[$shown_field];
			}
		}
		
		//print_r_pre($options);

		//$res = 'FK lov '.$fk_table.' '.print_r($fk_value, true);
		$res = form_dropdown($field, $options, $set_value, $attr);
		$res .= _MED_SEP.anchor_popup($controller.'/browse/table/'.encode_for_uri($fk_table).'/'.$this->create_uri_field_part($field).'/'.$this->create_uri_ref_field_part($fk_value[$field]), 'browse');
		return $res;
	}
}
